﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace TopShooter
{
	public class GodPlayer : PlayerEntity
	{
		static public GodPlayer Instance { get; private set; }

		public Entity.SelectionManager Selections;

		public bool IsWaitingLeftClick;

		public GodPlayer(bool isUserControlled)
			: base(isUserControlled)
		{
			TeamID = 1;
			IsInvulnerable = true;
			IsCollidable = false;
			IsSelectable = false;

			InputHandler.Instance.RegisterForKeyEvent(this, Keys.S, _IssueStopCommand, false, false);
			InputHandler.Instance.RegisterForKeyEvent(this, Keys.A, _RegisterAttackCommand, false, false);

			InputHandler.Instance.RegisterForMouseEvent(this, MouseEventTypes.ButtonClick, MouseButtons.Right, KeyboardModes.Normal, _IssueDefaultCommand);
			InputHandler.Instance.RegisterForMouseEvent(this, MouseEventTypes.ButtonClick, MouseButtons.Left, KeyboardModes.Normal, _IssueAttackCommand);

		}
		protected override void OnAddedToScene()
		{
			base.OnAddedToScene();
			Instance = this;
			Selections = new Entity.SelectionManager(Scene, this);
			Selections.Activate();
		}

		protected override void OnRemovedFromScene(Scene scene)
		{
			if (Instance == this)
				Instance = null;

			Selections.DeActivate();

			base.OnRemovedFromScene(scene);
		}

		private void _IssueDefaultCommand(MouseEvent evt)
		{
			foreach (Unit u in Selections.SelectedEntities)
			{
				Vector2 loc = new Vector2(evt.AbsoluteLocation.X, evt.AbsoluteLocation.Y);
				bool append = InputHandler.Instance.IsShiftPressed;
				u.IssueDefaultCommand(loc, append);
			}
		}
		private void _RegisterAttackCommand(Keys keys)
		{
			IsWaitingLeftClick = true;
		}
		private void _IssueAttackCommand(MouseEvent evt)
		{
			foreach (Unit u in Selections.SelectedEntities)
			{
				if (IsWaitingLeftClick)
				{
					Vector2 loc = new Vector2(evt.AbsoluteLocation.X, evt.AbsoluteLocation.Y);
					Entity e = Scene.Instance.FindSelectableEntityAtLocation((int)loc.X, (int)loc.Y);
					if (e == null)
						return;
					if (e.IsInvulnerable)
					{
						return;
					}
					bool append = InputHandler.Instance.IsShiftPressed;
					UnitCommand command;
					if (!append)
					{
						u.AbortAllCommands();
					}

					Entity target = Scene.Instance.FindSelectableEntityAtLocation((int)loc.X, (int)loc.Y);
					command = new UnitCommand.Attack(target);
					u.AddCommand(command);
				}
			}
			IsWaitingLeftClick = false;

		}
		private void _IssueStopCommand(Keys keys)
		{
			foreach (Unit u in Selections.SelectedEntities)
			{
				if (u.CommandQueue.Count == 0)
					continue;
				if (InputHandler.Instance.IsShiftPressed && u.CommandQueue.Count > 1)
				{
					u.CommandQueue.RemoveAt(u.CommandQueue.Count - 1);
				}
				else
				{
					u.AbortAllCommands();
				}
			}
		}
		private void _StopCommand(UnitCommand c)
		{
		}

		protected override void OnLoadContent()
		{
			_texture = Scene.Content.Load<Texture2D>("Entities/CrossHairs");
			_origin = new Vector2(_texture.Width / 2.0f, _texture.Height / 2.0f);
		}
		public override void Draw(SpriteBatch spriteBatch, Vector2 offset)
		{
			spriteBatch.Draw(_texture, Location + offset, null, Color, 0.0f, _origin, 0.1f, SpriteEffects.None, 0.0f);
			Game.Instance.PostDrawCommands += Selections.Draw;
		}

		protected override void DetermineBoost(KeyboardState keyboardState, GameTime gameTime)
		{
			if (!keyboardState.IsKeyDown(Keys.LeftShift))
			{
				_timeWhenBoostExpires = (long)gameTime.TotalGameTime.TotalMilliseconds + 300;
			}
		}


		public override void Update(GameTime gameTime)
		{
			base.Update(gameTime);
			Point mouseLoc = InputHandler.Instance.MouseScreenLocation;

			if (!InputHandler.Instance.IsMouseOverScreen)
				return;
			if (InputHandler.GetMouseState().LeftButton == ButtonState.Pressed)
				return;

			const float buffer = 50;
			const float maxSpeed = 1.5f;
			const double startDelay = 0.01f;
			_moveSpeed += 0.05f;
			if (_moveSpeed > maxSpeed)
				_moveSpeed = maxSpeed;

			Vector2 velocity = Vector2.Zero;

			if (mouseLoc.X < buffer)
			{
				velocity = new Vector2(-_moveSpeed, 0);
			}
			else if (mouseLoc.X > Game.Instance.ScreenSize.Width - buffer)
			{
				velocity = new Vector2(_moveSpeed, 0);
			}
			if (mouseLoc.Y < buffer)
			{
				velocity = new Vector2(0, -_moveSpeed);
			}
			else if (mouseLoc.Y > Game.Instance.ScreenSize.Height - buffer)
			{
				velocity = new Vector2(0, _moveSpeed);
			}

			if (velocity == Vector2.Zero)
			{
				_moveSpeed = 0;
				_timeWhenMovementStarts = 0;
			}
			else if (startDelay > 0)
			{	// Mouse is on border
				if (_timeWhenMovementStarts == 0)
				{	// First time
					_timeWhenMovementStarts = gameTime.TotalGameTime.TotalSeconds + startDelay;
					_movement = Vector2.Zero;
					_moveSpeed = 0;
				}
				else if (gameTime.TotalGameTime.TotalSeconds < _timeWhenMovementStarts)
				{
					_movement = Vector2.Zero;
					_moveSpeed = 0;
				}
				else
				{	// we're moving now
					_movement += velocity;
				}
			}
		}
		private float _moveSpeed = 0;
		private double _timeWhenMovementStarts;
	}
}
